package com.ksyun.start.camp;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ksyun.start.camp.model.ApiResponse;
import com.ksyun.start.camp.model.HeartInstance;
import com.ksyun.start.camp.model.LogInstance;
import com.ksyun.start.camp.model.ServiceInstance;
import com.ksyun.start.camp.model.vo.ApiServiceInstance;
import com.ksyun.start.camp.model.vo.ServiceInstanceVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 服务启动运行逻辑
 */
@Component
@Slf4j
public class ServiceAppRunner implements ApplicationRunner {

    @Autowired
    RestTemplate restTemplate;

    @Value("${spring.application.name}")
    private String serverName;

    @Value("${server.port}")
    private Integer port;

    @Value("${heart.time}")
    private Integer heartTime;

    @Autowired
    private Gson gson;

    private final String REGISTER_URL="http://localhost:8180/api/register";
    private final String SENDBEAT_URL="http://localhost:8180/api/heartbeat";
    private final String UNREGISTER_URL="http://localhost:8180/api/unregister";
    private final String LOGGING_URL="http://localhost:8320/api/logging";


    private final String REGISTRY_URL = "http://localhost:8180/api/discovery?name=";

    private ScheduledExecutorService executorService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 此处代码会在 Boot 应用启动时执行
        // 开始编写你的逻辑，下面是提示
        InetAddress localHost = InetAddress.getLocalHost();
        String ipAddress = localHost.getHostAddress();
        String serviceId= serverName+"_"+ipAddress+"_"+port;

        //在注册中心统一为各个参数去初始化时间
        ServiceInstance serviceInstance = new ServiceInstance(serverName,serviceId,ipAddress,port);
        HeartInstance heartInstance = new HeartInstance(serviceId, ipAddress, port);
        // 1. 向 registry 服务注册当前服务
        registerService(serviceInstance);
        // 2. 定期发送心跳逻辑
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(() -> sendHeartbeat(heartInstance), heartTime, heartTime, TimeUnit.SECONDS);
        // 发送日志记录请求
        executorService.scheduleAtFixedRate(() -> sendLog(serviceId), 0, 1, TimeUnit.SECONDS);
    }

    /**
     * 向注册中心注册当前服务
     */
    private void registerService(ServiceInstance serviceInstance) {
        // 发送 HTTP 请求或调用注册中心的注册接口，将 serviceInstance 注册到注册中心
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        //在请求体中放入Json类型的参数
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置请求头 Content-Type 为 JSON
        HttpEntity<ServiceInstance> requestEntity = new HttpEntity<>(serviceInstance, headers); // 将请求体 voucherJson 放入 HttpEntity

        // 发送 Post 请求并接收响应
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                REGISTER_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        String body = responseEntity.getBody();
        log.info(body);
    }

    /**
     * 发送心跳到注册中心
     */
    private void sendHeartbeat(HeartInstance heartInstance) {
        // 发送 HTTP 请求或调用注册中心的心跳接口，发送心跳信息给注册中心
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        //在请求体中放入Json类型的参数
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置请求头 Content-Type 为 JSON
        HttpEntity<HeartInstance> requestEntity = new HttpEntity<>(heartInstance, headers); // 将请求体 voucherJson 放入 HttpEntity
        // 发送 Post 请求并接收响应
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                SENDBEAT_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        String body = responseEntity.getBody();
        log.info(body);
        ApiResponse apiResponse = gson.fromJson(body, ApiResponse.class);
        int code = apiResponse.getCode();
        if(code==503){//当收到了心跳更新失败的响应时，心跳请求停止
            stopHeartbeat();
        }
    }

    private void stopHeartbeat() {
        if (executorService != null) {
            executorService.shutdown();
            log.info("心跳请求已停止");
        }
    }

    /**
     * 发送日志到日志收集服务端
     */
    private void sendLog(String serviceId) {
        // 构造日志信息
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        String logDateTime = now.format(formatter);

        String logLevel = "info"; // 日志级别可以根据需要设置
        String logMessage = "Client status is OK."; // 日志内容，根据需求设置

        // 构造日志实例对象
        LogInstance logInstance = new LogInstance();
        logInstance.setServiceName(serverName);
        logInstance.setServiceId(serviceId);
        logInstance.setLevel(logLevel);
        logInstance.setDatetime(logDateTime);
        logInstance.setMessage(logMessage);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        // 将日志实例放入请求体中
        HttpEntity<LogInstance> requestEntity = new HttpEntity<>(logInstance, headers);

        // 发送 Post 请求并接收响应
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                LOGGING_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );

        String body = responseEntity.getBody();

        log.info("日志记录情况:{}",body);
    }

    /**
     * 发送注销请求到注册中心
     */
    @PreDestroy
    private void unregisterService() throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        String ipAddress = localHost.getHostAddress();
        String serviceId= serverName+"_"+ipAddress+"_"+port;
        ServiceInstance serviceInstance = new ServiceInstance(serverName,serviceId,ipAddress,port);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<ServiceInstance> requestEntity = new HttpEntity<>(serviceInstance, headers);

        // 发送注销请求
        ResponseEntity<String> response = restTemplate.exchange(
                UNREGISTER_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        log.info("服务注销时间为:{}", LocalDateTime.now());
        String body = response.getBody();
        log.info(body);
    }

//    /**
//     * 发送日志到日志收集服务端
//     */
//    private void sendLog(String serviceId) {
//        //找到日志服务
//        String domain = getDomain("logging-service");
//
//        // 构造日志信息
//        LocalDateTime now = LocalDateTime.now();
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
//        String logDateTime = now.format(formatter);
//
//        String logLevel = "info"; // 日志级别可以根据需要设置
//        String logMessage = "Client status is OK."; // 日志内容，根据需求设置
//
//        // 构造日志实例对象
//        LogInstance logInstance = new LogInstance();
//        logInstance.setServiceName(serverName);
//        logInstance.setServiceId(serviceId);
//        logInstance.setLevel(logLevel);
//        logInstance.setDatetime(logDateTime);
//        logInstance.setMessage(logMessage);
//        // 设置请求头
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
//        // 将日志实例放入请求体中
//        HttpEntity<LogInstance> requestEntity = new HttpEntity<>(logInstance, headers);
//
//        // 发送 Post 请求并接收响应
//        ResponseEntity<String> responseEntity = restTemplate.exchange(
//                LOGGING_URL,
//                HttpMethod.POST,
//                requestEntity,
//                String.class
//        );
//
//        String body = responseEntity.getBody();
//
//        log.info("响应body is {}",body);
//    }
//
//    // 从注册中心轮询获取服务ip和端口
//    private String getDomain(String service) {
//        String url = REGISTRY_URL + service;
//
//        String serviceResponse = restTemplate.getForObject(url, String.class);
//
//        ApiServiceInstance apiServiceInstance = gson.fromJson(serviceResponse, ApiServiceInstance.class);
//        List<ServiceInstanceVO> serviceInstanceVOList = apiServiceInstance.getData();
//        ServiceInstanceVO serviceInstanceVO = serviceInstanceVOList.get(0);
//        String ipAddress = serviceInstanceVO.getIpAddress();
//        Integer port = serviceInstanceVO.getPort();
//        String domain = "http://" + ipAddress + ":" + port;
//        return domain;
//    }
}
